// Copyright (C) 2010  Joan Puigcerver Perez, <joapuipe@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

#ifndef __WORK_HPP__
#define __WORK_HPP__

#include <iostream>

#include <BasicTypes.hpp>

/**
 * \class Work
 * 
 * Class used to represent the work of a person in a movie.
 * Internally the work is represented as an 8-bit unsigned integer.
 * It can also represent a set of works, this useful in filtering process.
 * \see Filter
 *
 */
class Work {
private:
  uint8_t _work; // Work code
  
public:
  /** Actors code. */
  static const uint8_t ID_ACTOR;
  /** Directors code. */
  static const uint8_t ID_DIRECTOR;
  /** Producers code. */
  static const uint8_t ID_PRODUCER;
  /** Writers code. */
  static const uint8_t ID_WRITER;
  /** Unknown positions. */
  static const uint8_t ID_UNKNOWN;
  /** Wildcard very useful for filtering. */
  static const uint8_t ID_ALL;

  /** Actors string representation. */
  static const char *  TAG_ACTOR;
  /** Directors string representation. */
  static const char *  TAG_DIRECTOR;
  /** Producers string representation. */
  static const char *  TAG_PRODUCER;
  /** Writers string representation. */
  static const char *  TAG_WRITER;
  /** This is "Unknown". */
  static const char *  TAG_UNKNOWN;
  /** This is "All". */
  static const char *  TAG_ALL;
  
  /**
   * Constructor that sets the object to ID_UNKNOWN.
   */
  Work();

  /**
   * Constructor that sets the object from a given 8-bit integer value.
   * @param work Code of the desired work value.
   */
  Work(const uint8_t work);

  /**
   * Constructor that sets the object from a valid string representation.
   * @param work Name of the desired work, e.g: TAG_ACTOR.
   */
  Work(const char * work);

  /**
   * Operator that sets the object to a given 8-bit int value.
   * @param work Code of the desired media value.
   */
  Work& operator = (const uint8_t work);

  /**
   * Comparator that checks if two objects are equal.
   * @param work The other object.
   */  
  bool operator == (const Work& work) const;

  /**
   * Comparator that checks if a Work object is equal to a 
   * work represented as a 8-bit unsigned integer.
   * @param work Code of the second work.
   */
  bool operator == (const uint8_t work) const;

  /**
   * Distinct comparator that checks if two objects are
   * distinct.
   * @param work The other object.
   */
  bool operator != (const Work& work) const;

  /**
   * Distinct comparator that checks if a Work object is different to
   * a work represented as a 8-bit unsigned integer.
   * @param work Code of the second work.
   */
  bool operator != (const uint8_t work) const;

  /**
   * Operator that returns the internal code of the work as a
   * 8-bit unsigned int.
   */
  operator uint8_t () const;

  /**
   * Operator that returns the string representation of the work.
   */
  operator const char * () const;

  /**
   * Function that performs a bitwise AND operation between two Work objects.
   * This function is used to compare to Work objects treating them
   * as a set of works.
   * @param work_a Work object interpreted as a set.
   * @param work_b Work object interpreted as a set.
   * \retval true The two work sets have a common value.
   * \retval false The two work sets does not have any common value.
   */
  static bool mask(const Work& work_a, const Work& work_b);

  /**
   * Friend method used to write the work's string representation 
   * to a ostream object.
   */
  friend std::ostream& operator << (std::ostream& os, const Work& work)
  {
    os << (const char *)work;
    return os;
  }

};

#endif
